package com.dex4d.ui.dapp;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.webkit.URLUtil;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.dex4d.BuildConfig;
import com.dex4d.R;
import com.dex4d.core.AppToolBarBaseActivity;
import com.dex4d.core.AppToolbarBaseFragment;
import com.dex4d.core.CustomApplication;
import com.dex4d.core.ITabFragment;
import com.dex4d.glide.GlideUtil;
import com.dex4d.model.User;
import com.dex4d.ui.dapp.model.DappEvent;
import com.dex4d.ui.dapp.model.DappTrade;
import com.dex4d.ui.dapp.model.DoneEvent;
import com.dex4d.ui.dapp.model.History;
import com.dex4d.ui.dapp.model.HistoryDao;
import com.dex4d.ui.main.view.EditTextField;
import com.dex4d.ui.qr.utils.AddressUtils;
import com.framework.util.DisplayUtil;
import com.just.agentweb.AgentWeb;
import com.wallet.web3.OnGetBalanceListener;
import com.wallet.web3.OnSignMessageListener;
import com.wallet.web3.OnSignPersonalMessageListener;
import com.wallet.web3.OnSignTransactionListener;
import com.wallet.web3.OnSignTypedMessageListener;
import com.wallet.web3.OnVerifyListener;
import com.wallet.web3.URLLoadInterface;
import com.wallet.web3.URLLoadReceiver;
import com.wallet.web3.Web3View;
import com.wallet.web3.entity.Address;
import com.wallet.web3.entity.Message;
import com.wallet.web3.entity.TypedData;
import com.wallet.web3.entity.Web3Transaction;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.lang.reflect.Field;

import butterknife.BindView;
import butterknife.OnClick;
import me.shaohui.bottomdialog.BottomDialog;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;


public class DappBrowserFragment extends AppToolbarBaseFragment
        implements ITabFragment
        , OnSignTransactionListener
        , OnSignPersonalMessageListener
        , OnSignTypedMessageListener
        , OnSignMessageListener
        , OnVerifyListener
        , OnGetBalanceListener
        , URLLoadInterface
        , DappTrade.OnTransferListener {


    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    private String currentWebUrl=BuildConfig.DAPP_HOME;

    private String mParam1;
    private String mParam2;

    public DappBrowserFragment() {
        // Required empty public constructor
    }

    private URLLoadReceiver URLReceiver;

    private DappTrade dappTrade;

    private AgentWeb agentWeb;

    Web3View web3;

    @BindView(R.id.rootView)
    LinearLayout rootView;

    @BindView(R.id.browser_home)
    ImageView browser_home;

    @BindView(R.id.browser_left)
    ImageView browser_left;

    @BindView(R.id.browser_favorite)
    ImageView browser_favorite;

    @BindView(R.id.browser_more)
    ImageView browser_more;

    @BindView(R.id.browser_search)
    ImageView browser_search;

    @BindView(R.id.url_tv)
    EditTextField url_tv;

    @BindView(R.id.web_container)
    LinearLayout container;


    public static DappBrowserFragment newInstance(String param1, String param2) {
        DappBrowserFragment fragment = new DappBrowserFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }

        EventBus.getDefault().register(this);

        URLReceiver = new URLLoadReceiver(getActivity(), this);
        dappTrade = new DappTrade(getActivity(), this);

    }


    @Override
    protected int getLayoutId() {
        return R.layout.fragment_dapp_browser;
    }

    @Override
    protected void initToolbar(AppToolBarBaseActivity mContent) {
        mContent.mToolbar.setVisibility(View.GONE);
    }

    @Override
    protected void initVariables() {

        rootView.setPadding(0,getStatusBarHeight(),0,0);

        web3 = new Web3View(getActivity());
        setupWeb3();
        agentWeb = AgentWeb.with(this)
                .setAgentWebParent(container, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
                .useDefaultIndicator()
                .setWebViewClient(new DappWebViewClient())
                .setWebChromeClient(new DappWebChromeClient())
                .setWebView(web3)
                .createAgentWeb()
                .ready()
                .go("https://www.jianshu.com");

        url_tv.setOnEditorActionListener((v, actionId, event) -> {

            switch (actionId) {
                case EditorInfo.IME_ACTION_DONE:
                case EditorInfo.IME_ACTION_GO:
                case EditorInfo.IME_ACTION_SEARCH:
                case EditorInfo.IME_ACTION_SEND:
                case EditorInfo.IME_ACTION_NEXT:
                    loadUrl(v.getText().toString().trim());
                    return true;

                default:
                    return false;
            }

        });

    }

    @Override
    protected void loadData() {
    }

    @Override
    public void onMenuItemClick() {

    }

    @Override
    public Fragment getFragment() {
        return this;
    }

    @Override
    public String getTitle() {
        return null;
    }

    private void setupWeb3() {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG);
        }

        web3.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        web3.clearCache(false);

        web3.setChainId(BuildConfig.CHAIN_ID);
        web3.setRpcUrl(BuildConfig.RPC_URL);
        web3.setWalletAddress(new Address(User.getInstance().getAddress()));

        web3.setOnSignMessageListener(this);
        web3.setOnSignPersonalMessageListener(this);
        web3.setOnSignTransactionListener(this);
        web3.setOnSignTypedMessageListener(this);
        web3.setOnVerifyListener(this);
        web3.setOnGetBalanceListener(this);
    }

    /**
     * 加载URL
     *
     * @param url
     */
    private void loadUrl(String url) {
        String toUrl = BuildConfig.DAPP_HOME;
        if (TextUtils.isEmpty(url)) {
            toUrl = BuildConfig.DAPP_HOME;
        } else {
            toUrl = formatUrl(url);
        }
        url_tv.setText(toUrl);
        url_tv.setSelection(toUrl.length());
        web3.loadUrl(toUrl);
    }

    /**
     * 格式化URL
     *
     * @param url
     * @return
     */
    public String formatUrl(String url) {
        if (URLUtil.isHttpsUrl(url) || URLUtil.isHttpUrl(url)) {
            return url;
        } else {
            return "http://" + url;
        }
    }

    @Override
    public void onGetBalance(String balance) {

    }

    @Override
    public void onSignMessage(Message<String> message) {

    }

    @Override
    public void onSignPersonalMessage(Message<String> message) {

    }

    @Override
    public void onSignTransaction(Web3Transaction transaction, String url) {
        dappTrade.setTransaction(transaction);
        ConfirmationActivity.open(getActivity(), transaction, url);
    }

    @Override
    public void onSignTypedMessage(Message<TypedData[]> message) {

    }

    @Override
    public void onVerify(String message, String signHex) {

    }

    @Override
    public void onWebPageLoaded(String url, String title, Bitmap icon) {

        currentWebUrl=url;

        //是否显示回退按钮

        if (web3.canGoBack()) {
            browser_left.setVisibility(View.VISIBLE);
        } else {
            browser_left.setVisibility(View.GONE);
        }

        if (!TextUtils.isEmpty(title)) {
            url_tv.setText(title);
            url_tv.setSelection(title.length());
        } else {
            url_tv.setText(url);
        }

        Observable.create((Observable.OnSubscribe<History>) subscriber -> {
            //查看当前URL是否存在于数据库
            HistoryDao dao = CustomApplication.getDb().browserDao();
            History history = dao.getItemFromMd5(AddressUtils.md5(url));

            //新增加一条数据
            if (history == null) {
                history = new History(url, title);
                dao.insertItem(history);
            }

            //更新时间戳
            else {
                history.updateTimestamp();
                dao.updateTimeStampFromId(history.timestamp, history.id);
            }

            subscriber.onNext(history);
            subscriber.onCompleted();

        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(history -> {
                    if (history.bookmark == 1) {
                        browser_favorite.setImageResource(R.drawable.dapp_browser_favorite_ed);
                    } else {
                        browser_favorite.setImageResource(R.drawable.dapp_browser_favorite);
                    }

                    GlideUtil.displayImg(browser_search, history.icon);

                    dismissKeyboard();
                });
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {
            dappTrade.trade();
        }
    }

    @Override
    public void onDestroy() {
        if (getContext() != null) getContext().unregisterReceiver(URLReceiver);
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }

    @Override
    public void success(Web3Transaction transaction, String result) {
        web3.onSignTransactionSuccessful(transaction, result);
    }

    @Override
    public void error(Web3Transaction transaction, String result) {
        web3.onSignError(transaction, result);
    }

    /**
     * 更新列表
     *
     * @param dappEvent
     */
    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    public void dappTrade(DappEvent dappEvent) {
        if (dappEvent.isSign()) {
            dappTrade.trade();
        } else {
            web3.onSignCancel(dappEvent.getTransaction());
        }
    }

    /**
     * 确认支付成功失败
     *
     * @param doneEvent
     */
    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    public void dappDone(DoneEvent doneEvent) {
        web3.onSignTransactionSuccessful(doneEvent.transaction, doneEvent.hash);
    }

    /**
     * 通过浏览历史加载页面
     *
     * @param history
     */
    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    public void dappWeb(History history) {
        loadUrl(history.url);
    }

    /**
     * 返回主页
     */
    @OnClick(R.id.browser_home)
    public void backHome() {
        loadUrl(BuildConfig.DAPP_HOME);
    }

    /**
     * 网站回退
     */
    @OnClick(R.id.browser_left)
    public void preWeb() {
        //当浏览器中有缓存时展示
        web3.goBack();
    }

    /**
     * 点击收藏按钮
     */
    @OnClick(R.id.browser_favorite)
    public void like() {
        String url = web3.getUrl();
        Observable.create((Observable.OnSubscribe<History>) subscriber -> {
            //查看当前URL是否存在于数据库
            HistoryDao dao = CustomApplication.getDb().browserDao();
            History history = dao.getItemFromMd5(AddressUtils.md5(url));
            history.like();
            dao.updateBookMarkFromId(history.bookmark, history.id);

            History temp = dao.getItemFromMd5(AddressUtils.md5(url));
            subscriber.onNext(history);
            subscriber.onCompleted();
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(history -> {
                    if (history.bookmark == 1) {
                        browser_favorite.setImageResource(R.drawable.dapp_browser_favorite_ed);
                    } else {
                        browser_favorite.setImageResource(R.drawable.dapp_browser_favorite);
                    }
                });
    }

    /**
     * 点击更多
     */
    @OnClick(R.id.browser_more)
    public void moreMenu() {
        BottomDialog.create(getChildFragmentManager())
                .setViewListener(v -> {
                    // // You can do any of the necessary the operation with the view
                    TextView browser_bookmark = (TextView) v.findViewById(R.id.browser_bookmark);
                    TextView browser_refresh = (TextView) v.findViewById(R.id.browser_refresh);
                    TextView browser_cancel = (TextView) v.findViewById(R.id.browser_cancel);

                    browser_bookmark.setOnClickListener(v1 -> {
                        WebHistoryActivity.start(getActivity());
                        DialogFragment fragment = (DialogFragment) getChildFragmentManager().findFragmentByTag("BottomDialog");
                        if (fragment != null) fragment.dismiss();
                    });

                    browser_refresh.setOnClickListener(v12 -> {
                        if (!TextUtils.isEmpty(currentWebUrl)) loadUrl(currentWebUrl);
                        DialogFragment fragment1 = (DialogFragment) getChildFragmentManager().findFragmentByTag("BottomDialog");
                        if (fragment1 != null) fragment1.dismiss();
                    });

                    browser_cancel.setOnClickListener(v13 -> {
                        DialogFragment fragment12 = (DialogFragment) getChildFragmentManager().findFragmentByTag("BottomDialog");
                        if (fragment12 != null) fragment12.dismiss();
                    });

                })
                .setLayoutRes(R.layout.dapp_bottom_dialog2)
                .setDimAmount(0.1f)            // Dialog window dim amount(can change window background color）, range：0 to 1，default is : 0.2f
                .setCancelOutside(true)     // click the external area whether is closed, default is : true
                .setTag("BottomDialog")     // setting the DialogFragment tag
                .show();

    }

    static class DappWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            return false;
        }
    }


    static class DappWebChromeClient extends WebChromeClient {
        @Override
        public void onProgressChanged(WebView webview, int newProgress) {

        }

        @Override
        public void onReceivedTitle(WebView view, String title) {
            super.onReceivedTitle(view, title);
        }

        @Override
        public void onReceivedIcon(WebView view, Bitmap icon) {
            super.onReceivedIcon(view, icon);
        }

    }


    private void dismissKeyboard() {
        try {
            InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(url_tv.getWindowToken(), 0);
        } catch (NullPointerException e) {
            System.out.println("Pre - init");
        }
    }

    private int getStatusBarHeight() {
        Class<?> c = null;

        Object obj = null;

        Field field = null;

        int x = 0, sbar = 0;

        try {

            c = Class.forName("com.android.internal.R$dimen");

            obj = c.newInstance();

            field = c.getField("status_bar_height");

            x = Integer.parseInt(field.get(obj).toString());

            sbar = getContext().getResources().getDimensionPixelSize(x);

        } catch (Exception e1) {
            e1.printStackTrace();
            sbar = DisplayUtil.dip2px(getActivity(), 24);
        }
        return sbar;
    }


}
